#! /usr/bin/env python

# -*- coding: UTF-8 -*-
# ==============================================================================
# Filename : SearchBar.py
# Purpose  : 
# Author   : Yohann Li (lyh001686@sina.com)
# Date     : 2020-07-02 16:02
# ==============================================================================
import os

from PyQt5.QtCore import Qt, pyqtSignal, QRegularExpression
from PyQt5.QtGui import QIcon, QTextDocument, QKeySequence, QHideEvent
from PyQt5.QtWidgets import QHBoxLayout, QToolButton, QLineEdit, QWidget, QCheckBox, QLabel, QShortcut

from conf.configuration import logger, img_path


class SearchBar(QWidget):
    find_request_signal = pyqtSignal(dict)
    search_bar_hide_signal = pyqtSignal()

    def __init__(self, *args, **kwargs):
        super(SearchBar, self).__init__(*args, **kwargs)
        self.expression = ''
        self.setObjectName('SearchBar')
        self.find_edit = QLineEdit(self)
        self.up_search_btn = QToolButton(self)
        self.down_search_btn = QToolButton(self)
        self.word_box = QCheckBox('Word', self)
        self.word_box.setToolTip('Whole Word')
        self.re_box = QCheckBox('RegEx', self)
        self.re_box.setToolTip('Regular Expression')
        self.case_box = QCheckBox('Match Case', self)
        self.case_box.setToolTip('Case Sensitive')
        self.result_label = QLabel('No matches', self)
        self.close_btn = QToolButton(self)

        self.setup_widget()
        self.lay_widget()
        self.setWindowFlag(Qt.FramelessWindowHint)
        self.set_signal()
        self.set_shorcut()

    def setup_widget(self):
        self.find_edit.setClearButtonEnabled(True)
        self.find_edit.setObjectName('find_edit')
        self.find_edit.setAttribute(Qt.WA_MacShowFocusRect, 0)  # 设置隐藏蓝色边框
        self.up_search_btn.setObjectName('arrow_l')
        # self.up_search_btn.setAutoRaise(True)
        self.up_search_btn.setIcon(QIcon(os.path.join(img_path, 'arrow_l.png')))
        self.down_search_btn.setObjectName('arrow_r')
        # self.down_search_btn.setAutoRaise(True)
        self.down_search_btn.setIcon(QIcon(os.path.join(img_path, 'arrow_r.png')))
        # self.close_btn.setAutoRaise(True)
        self.close_btn.setIcon(QIcon(os.path.join(img_path, 'close.png')))
        self.close_btn.setObjectName('search_bar_close_btn')

    def set_signal(self):
        self.close_btn.clicked.connect(self.hide)  # 关闭按钮
        self.find_edit.returnPressed.connect(self.send_find_request)  # 回车
        self.re_box.stateChanged.connect(self.re_box_checked)
        self.case_box.stateChanged.connect(self.case_box_checked)
        self.word_box.stateChanged.connect(self.word_box_checked)
        self.up_search_btn.clicked.connect(self.up_search_btn_clicked)
        self.down_search_btn.clicked.connect(self.down_search_btn_clicked)

    def set_shorcut(self):
        QShortcut(QKeySequence.FindNext, self).activated.connect(self.down_search_btn_clicked)
        QShortcut(QKeySequence.FindPrevious, self).activated.connect(self.up_search_btn_clicked)

    def lay_widget(self):
        lay = QHBoxLayout(self)
        lay.addWidget(self.find_edit)
        lay.addSpacing(20)
        lay.addWidget(self.up_search_btn)
        lay.addWidget(self.down_search_btn)
        lay.addSpacing(20)
        lay.addWidget(self.word_box)
        lay.addSpacing(20)
        lay.addWidget(self.case_box)
        lay.addSpacing(20)
        lay.addWidget(self.re_box)
        lay.addSpacing(20)
        lay.addWidget(self.result_label)
        lay.addSpacing(10)
        lay.addWidget(self.close_btn)
        lay.setSpacing(0)
        lay.setContentsMargins(0, 0, 0, 0)

    def up_search_btn_clicked(self):
        self.send_find_request(QTextDocument.FindBackward)

    def down_search_btn_clicked(self):
        self.send_find_request()

    def re_box_checked(self, state: int):
        if state:
            self.word_box.setChecked(False)
            self.word_box.setDisabled(True)
        else:
            self.word_box.setEnabled(True)
        self.send_find_request()

    def case_box_checked(self, state: int):
        self.send_find_request()

    word_box_checked = case_box_checked

    def send_find_request(self, op=0):
        text = self.find_edit.text()
        if not text:  # 如果没有搜索内容则拦截信号
            return
        if self.re_box.isChecked():
            text = QRegularExpression(text)
            text.setPatternOptions(QRegularExpression.CaseInsensitiveOption) if not self.case_box.isChecked() else ''
            logger.debug(f"Pattern {repr(text)}")
        options, word, case = self._set_options(op)
        direction = 'up' if op else 'down'
        request = {'exp': text,
                   'options': options,
                   'direction': direction,
                   'word': word,
                   'case': case}
        logger.debug(f"sending find request {request}")
        self.find_request_signal.emit(request)

    def _set_options(self, options=0):
        """点击搜索栏check box的时候，更改QTextDocument.FindFlags"""
        word = case = False
        if self.word_box.isChecked():
            logger.debug(f'Find whole word checked')
            options |= QTextDocument.FindWholeWords
            word = True
        # if self.case_box.isChecked() and not self.re_box.isChecked():
        if self.case_box.isChecked():
            logger.debug(f'Find case sensitively checked')
            options |= QTextDocument.FindCaseSensitively
            case = True
        return options, word, case

    def set_n_matches(self, count: int):
        logger.debug(f"received count {count}")
        self.result_label.setText(f"{count} matches")

    def hideEvent(self, a0: QHideEvent) -> None:
        self.search_bar_hide_signal.emit()
        return super(SearchBar, self).hideEvent(a0)